/*
*	Copyright (c) 2009 Brent Mombourquette
*
*	Permission is hereby granted, free of charge, to any person
*	obtaining a copy of this software and associated documentation
*	files (the "Software"), to deal in the Software without
*	restriction, including without limitation the rights to use,
*	copy, modify, merge, publish, distribute, sublicense, and/or sell
*	copies of the Software, and to permit persons to whom the
*	Software is furnished to do so, subject to the following
*	conditions:
*
*	The above copyright notice and this permission notice shall be
*	included in all copies or substantial portions of the Software.
*
*	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
*	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
*	OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
*	NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
*	HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
*	WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
*	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
*	OTHER DEALINGS IN THE SOFTWARE.
*
*	This file contains functions called from graph_page.html and its imported Javascripts that involve manipulating
*	breadCrumbs.sqlite. 
*/
// Import a referrence to the BreadCrumbs database
Components.utils.import("resource://BreadCrumbs/database.jsm");

var database = {
	/*
	 * Get the number of rows in the database
	 * @return {Number}
	 */
	getRows: function() {
		var getRowsString = "SELECT COUNT(*) FROM edgeLog;";
		var getRowsStatement = breadcrumbsDBConn.createStatement(getRowsString);
		var rows = 0;
		try {
			while(getRowsStatement.executeStep()){
				rows = getRowsStatement.getInt64(0);
			}
		} finally {
			getRowsStatement.reset();
			getRowsStatement.finalize();
		}
		return rows
	},

	/*
	 * Return the largest row number in the database
	 * @return {Integer} maxRow
	 */
	getMaxRow: function() {
		var getMaxRowString = "SELECT MAX(row) FROM edgeLog;";
		var getMaxRowStatement = breadcrumbsDBConn.createStatement(getMaxRowString);
		var maxRow;
		try {
			while(getMaxRowStatement.executeStep()){
				maxRow = getMaxRowStatement.getInt32(0);
			}
		} finally {
			getMaxRowStatement.reset();
			getMaxRowStatement.finalize();
		}
		
		return maxRow;
	},
	
	/*
	 * Extract the contents of row idx from the database.
	 * @param {Number} idx		Row index of the database to extract
	 * @return {Object}		A dictionary object of entries of row idx in the database
	 */
	extractRow: function(idx) {
		var getNextString = "SELECT destination,source,title,annotation,fav,permTitle,timeEnter,linkType,image,cords FROM edgeLog WHERE row=?1;";
		var getNextStatement = breadcrumbsDBConn.createStatement(getNextString);
		getNextStatement.bindInt32Parameter(0, idx);
		
		var res = new Object();
		try {
			while(getNextStatement.executeStep()){
				res['destination'] = getNextStatement.getUTF8String(0);
				res['source'] = getNextStatement.getUTF8String(1);
				res['title'] = getNextStatement.getUTF8String(2);
				res['ann'] = getNextStatement.getUTF8String(3);
				res['fav'] = getNextStatement.getUTF8String(4);
				res['permTitle'] = getNextStatement.getUTF8String(5);
				res['timeEnter'] = getNextStatement.getUTF8String(6);
				res['linkType'] = getNextStatement.getInt32(7);
				res['image'] = getNextStatement.getUTF8String(8);
				res['cords'] = getNextStatement.getUTF8String(9);
			}
		} finally {
			getNextStatement.reset();
			getNextStatement.finalize();
		}
		res['idx'] = idx;
		return res;
	},
	
	/*
	 * Return the title of the entry at row row in the database.
	 * @param {Integer} row
	 * @return {String} title
	 */
	getTitle: function(row) {
		var getNewAnnotation = "SELECT title FROM edgeLog WHERE row=?1;";
		var getNewAnnotationStatement = breadcrumbsDBConn.createStatement(getNewAnnotation);
		getNewAnnotationStatement.bindInt32Parameter(0, row); 
		
		var title;
		try {
			while(getNewAnnotationStatement.executeStep()){
				title = getNewAnnotationStatement.getUTF8String(0);
			}
		} finally {
			getNewAnnotationStatement.reset();
			getNewAnnotationStatement.finalize();
		}
		
		return title;
	},
	
	/*
	 * Return the annotation of edge from the database.
	 * @param {SVG Polyline} edge
	 * @return {String} annotation
	 */
	getAnnotation: function(edge) {
		var getNewAnnotation = "SELECT annotation FROM edgeLog WHERE row=?1;";
		var getNewAnnotationStatement = breadcrumbsDBConn.createStatement(getNewAnnotation);
		getNewAnnotationStatement.bindInt32Parameter(0, edge.idx); 
		
		var annotation;
		try {
			while(getNewAnnotationStatement.executeStep()){
				annotation = getNewAnnotationStatement.getUTF8String(0);
			}
		} finally {
			getNewAnnotationStatement.reset();
			getNewAnnotationStatement.finalize();
		}
		
		return annotation;
	},
	
	/*
	 * Delete the entry for this node and any edge that may lead to it.
	 * @param {DataNode} node
	 */
	deleteNode: function(node) {
		//Delete all edges coming from this node
		var delNodeString = "DELETE FROM edgeLog WHERE destination=?1;"
		var delNodeStatement = breadcrumbsDBConn.createStatement(delNodeString);
		delNodeStatement.bindUTF8StringParameter(0, node.url);
		delNodeStatement.execute();
		delNodeStatement.finalize();
		
		//Alter all edges who's source was this node to have EMPTY_SOURCE_ENTRY as their updated source
		var setSourceString = "UPDATE edgeLog SET source=?1 WHERE source=?2";
		var setSourceStatement = breadcrumbsDBConn.createStatement(setSourceString);
		setSourceStatement.bindUTF8StringParameter(0, 'EMPTY_SOURCE_ENTRY');
		setSourceStatement.bindUTF8StringParameter(1, node.url);
		setSourceStatement.execute();
		setSourceStatement.finalize();
	},
	
	/*
	 * Extract the destionation, source, and title assocaited with the database entry with row = edge.idx
	 * @param {SVG Polyline} edge
	 * @return {Object} 				A dictionary with the destionation, source, and title
	 */
	getEdgeProperties: function(edge) {
		var getDestString = "SELECT destination,source,title FROM edgeLog WHERE row=?1;";
		var getDestStatement = breadcrumbsDBConn.createStatement(getDestString);
		// Note: edge.id = 'edge:#'      edge.idx = '#'
		getDestStatement.bindInt32Parameter(0, edge.idx);
		
		var dest, sor, t;
		try {
			while(getDestStatement.executeStep()){
				dest = getDestStatement.getUTF8String(0);
				sor = getDestStatement.getUTF8String(1);
				t = getDestStatement.getUTF8String(2);
			}
		} finally {
			getDestStatement.reset();
			getDestStatement.finalize();
		}
		
		return {destination: dest, source: sor, title: t};
	},
	
	/*
	 * Attempt to extract the an edge that was added after the entry that props describes, yet has the same destination value.
	 * @param {Object} props		Attributes: props.destination, props.source, props.title.
	 *						These are properties of an entry in the database.
	 * @retrurn {Integer} row
	 */
	getNextRow: function(props) {
		// This looks to see if there is another row in the database that has the same destination.
		var isRootString = "SELECT row FROM edgeLog WHERE destination=?1 AND NOT ( source=?2 );"
		var isRootStatement = breadcrumbsDBConn.createStatement(isRootString);
		isRootStatement.bindUTF8StringParameter(0, props.destination);
		isRootStatement.bindUTF8StringParameter(1, props.source);
		
		var row;
		try {
			while(isRootStatement.executeStep()){
				if (row) { // This ensures row is the FIRST entry in the DB that does not have row=edge.idx and meets above conditions
					continue;
				} else {
					row = isRootStatement.getInt32(0);
				}
			}
		} finally {
			isRootStatement.reset();
			isRootStatement.finalize();
		}
		
		return row;
	},
	
	/*
	 * Set the title column to newTitle for row rowToUpdate in the BreadCrumbs database.
	 * @param {Integer} rowToUpdate
	 * @param {String} newTitle
	 */
	updateTitle: function(rowToUpdate, newTitle) {
		var updateString = "UPDATE edgeLog SET title=?1 WHERE row=?2;";
		var updateStatement = breadcrumbsDBConn.createStatement(updateString);
		updateStatement.bindUTF8StringParameter(0, newTitle);
		updateStatement.bindInt32Parameter(1, rowToUpdate);
		updateStatement.execute();
		updateStatement.finalize();
	},
	
	/*
	 * Delete the row rowToDelete in the BreadCrumbs database.
	 * @param {Integer} rowToDelete
	 */
	deleteRow: function(rowToDelete) {
		var delString = "DELETE FROM edgeLog WHERE row=?1;";
		var delStatement = breadcrumbsDBConn.createStatement(delString);
		delStatement.bindInt32Parameter(0, rowToDelete);
		delStatement.execute();
		delStatement.finalize();
	},
	
	/* 
	 * Set the source column to emtpy for row rowToEmtpy in the BreadCrumbs database.
	 * @param {Integer} rowToEmtpy
	 */
	nullifySource: function(rowToEmpty) {
		var updateString = "UPDATE edgeLog SET source=?1 WHERE row=?2;";
		var updateStatement = breadcrumbsDBConn.createStatement(updateString);
		var emptyString = "EMPTY_SOURCE_ENTRY";
		updateStatement.bindUTF8StringParameter(0, emptyString);
		updateStatement.bindInt32Parameter(1, rowToEmpty);
		updateStatement.execute();
		updateStatement.finalize();
	},
	
	/*
	 * Update the database row rowID to have "x,y" in its cords collumn.
	 * @param {Integer} rowID
	 * @param {Integer} x
	 * @param {Integer} y
	 */
	updateCords: function (rowID, x, y) {
		var newCord = x + "," + y; 
		var updateString = "UPDATE edgeLog SET cords=?1 WHERE row=?2;";
		var updateStatement = breadcrumbsDBConn.createStatement(updateString);
		updateStatement.bindUTF8StringParameter(0, newCord);
		updateStatement.bindInt32Parameter(1, rowID);
		updateStatement.execute();
		updateStatement.finalize();
	},
	
	/*
	* Delete the contents of the database.
	*/
	deleteAll: function() {		
		var deleteDatabaseString = "DELETE FROM edgeLog;";
		var deleteDatabaseStatement = breadcrumbsDBConn.createStatement(deleteDatabaseString);
		
		try {
			while(deleteDatabaseStatement.executeStep()){
			}
		} finally {
			deleteDatabaseStatement.reset();
			deleteDatabaseStatement.finalize();
		}
	}
}